package com.fept.msgcore.scheduler.job.manager;

import com.fept.msgcore.scheduler.job.base.BaseScheduleJob;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.util.List;

/**
 * Created by Srma on 2/10/2017.
 */
public class ScheduleManager {
    private static Logger logger = LoggerFactory.getLogger(ScheduleManager.class);

    private static String DEFAULT_JOB_GROUP_NAME = "DEFAULT_JOBGROUP_NAME";
    private static String DEFAULT_TRIGGER_GROUP_NAME = "DEFAULT_TRIGGERGROUP_NAME";
    private SchedulerFactory schedulerFactory;
    private static ScheduleManager instance = new ScheduleManager();

    public static ScheduleManager getInstance() {
        return instance;
    }

    public List<?> listCurrentlyExecutingJobs() throws SchedulerException {
        return this.schedulerFactory.getScheduler().getCurrentlyExecutingJobs();
    }

    public void register(BaseScheduleJob job) throws SchedulerException, ParseException {
        logger.info(String.format("register job: %s", new Object[]{job.getJobName()}));
        this.addJob(job.getJobName(), job.getClass(), job.getTimeExpression());
    }

    public void unregister(BaseScheduleJob job) throws SchedulerException {
        logger.info(String.format("unregister job: %s", new Object[]{job.getJobName()}));
        this.removeJob(job.getJobName());
    }

    private ScheduleManager() {
        try {
            this.schedulerFactory = new StdSchedulerFactory();
            this.startup();
        } catch (Exception var2) {
            logger.error("exception on initializing ScheduleManager");
            logger.error(var2.getMessage());
            throw new RuntimeException(var2);
        }
    }

    public void addJob(String jobName, Class<?> cls, String time) throws SchedulerException, ParseException {
        Scheduler sched = this.schedulerFactory.getScheduler();
        JobDetail jobDetail = new JobDetail(jobName, DEFAULT_JOB_GROUP_NAME, cls);
        CronTrigger trigger = new CronTrigger(jobName, DEFAULT_TRIGGER_GROUP_NAME);
        trigger.setCronExpression(time);
        sched.scheduleJob(jobDetail, trigger);
    }

    public void modifyJobTime(String jobName, String time) throws SchedulerException, ParseException {
        Scheduler sched = this.schedulerFactory.getScheduler();
        CronTrigger trigger = (CronTrigger)sched.getTrigger(jobName, DEFAULT_TRIGGER_GROUP_NAME);
        if(trigger != null) {
            String oldTime = trigger.getCronExpression();
            if(!oldTime.equalsIgnoreCase(time)) {
                JobDetail jobDetail = sched.getJobDetail(jobName, DEFAULT_JOB_GROUP_NAME);
                Class objJobClass = jobDetail.getJobClass();
                this.removeJob(jobName);
                this.addJob(jobName, objJobClass, time);
            }

        }
    }

    public void removeJob(String jobName) throws SchedulerException {
        Scheduler sched = this.schedulerFactory.getScheduler();
        sched.pauseTrigger(jobName, DEFAULT_TRIGGER_GROUP_NAME);
        sched.unscheduleJob(jobName, DEFAULT_TRIGGER_GROUP_NAME);
        sched.deleteJob(jobName, DEFAULT_JOB_GROUP_NAME);
    }

    public void addJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName, Class<?> jobClass, String time) throws SchedulerException, ParseException {
        Scheduler sched = this.schedulerFactory.getScheduler();
        JobDetail jobDetail = new JobDetail(jobName, jobGroupName, jobClass);
        CronTrigger trigger = new CronTrigger(triggerName, triggerGroupName);
        trigger.setCronExpression(time);
        sched.scheduleJob(jobDetail, trigger);
    }

    public void modifyJobTime(String triggerName, String triggerGroupName, String time) throws SchedulerException, ParseException {
        Scheduler sched = this.schedulerFactory.getScheduler();
        CronTrigger trigger = (CronTrigger)sched.getTrigger(triggerName, triggerGroupName);
        if(trigger != null) {
            String oldTime = trigger.getCronExpression();
            if(!oldTime.equalsIgnoreCase(time)) {
                trigger.setCronExpression(time);
                sched.resumeTrigger(triggerName, triggerGroupName);
            }

        }
    }

    public void removeJob(String jobName, String jobGroupName, String triggerName, String triggerGroupName) throws SchedulerException {
        Scheduler sched = this.schedulerFactory.getScheduler();
        sched.pauseTrigger(triggerName, triggerGroupName);
        sched.unscheduleJob(triggerName, triggerGroupName);
        sched.deleteJob(jobName, jobGroupName);
    }

    public synchronized void shutdown() throws SchedulerException {
        this.schedulerFactory.getScheduler().shutdown();
    }

    private void startup() throws SchedulerException {
        this.schedulerFactory.getScheduler().start();
    }
}
